import {HttpContext} from '@angular/common/http';
import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  Inject,
  OnDestroy,
  OnInit,
  Optional
} from '@angular/core';
import {AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {Router} from '@angular/router';
import {StartupService} from '@core';
import {ReuseTabService} from '@delon/abc/reuse-tab';
import {ALLOW_ANONYMOUS, DA_SERVICE_TOKEN, ITokenModel, ITokenService, SocialService} from '@delon/auth';
import {_HttpClient, SettingsService} from '@delon/theme';
import {NzTabChangeEvent} from 'ng-zorro-antd/tabs';
import {finalize} from 'rxjs/operators';
import {Api} from 'src/app/shared/api/api';
import {
  decryptByRSA,
  encryptByRSA,
  generateRsaKeyWithPKCS8,
  signBySHA256WithRSA,
  verifyBySHA256WithRSA
} from 'src/app/shared/utils/crypto';
import {ResponseCode} from "../../../shared/response.code";
import {NzMessageService} from "ng-zorro-antd/message";

@Component({
  selector: 'passport-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.less'],
  providers: [SocialService],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserLoginComponent implements OnInit, OnDestroy {
  constructor(
    fb: UntypedFormBuilder,
    private router: Router,
    private settingsService: SettingsService,
    private socialService: SocialService,
    @Optional()
    @Inject(ReuseTabService)
    private reuseTabService: ReuseTabService,
    @Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService,
    private startupSrv: StartupService,
    private settingService: SettingsService,
    private msg: NzMessageService,
    private http: _HttpClient,
    private cdr: ChangeDetectorRef
  ) {
    this.form = fb.group({
      userName: [null, [Validators.required, Validators.minLength(4)]],
      password: [null, [Validators.required]],
      mobile: [null, [Validators.required, Validators.pattern(/^1\d{10}$/)]],
      captcha: [null, [Validators.required]],
      remember: [true]
    });
  }

  publicKey: string = '';


  get userName(): AbstractControl {
    return this.form.get('userName')!;
  }
  get password(): AbstractControl {
    return this.form.get('password')!;
  }
  get mobile(): AbstractControl {
    return this.form.get('mobile')!;
  }
  get captcha(): AbstractControl {
    return this.form.get('captcha')!;
  }
  form: UntypedFormGroup;
  error = '';
  type = 0;
  loading = false;

  count = 0;
  interval$: any;

  ngOnInit(): void {
  }

  switch({ index }: NzTabChangeEvent): void {
    this.type = index!;
  }

  getCaptcha(): void {
    if (this.mobile.invalid) {
      this.mobile.markAsDirty({ onlySelf: true });
      this.mobile.updateValueAndValidity({ onlySelf: true });
      return;
    }
    this.count = 59;
    this.interval$ = setInterval(() => {
      this.count -= 1;
      if (this.count <= 0) {
        clearInterval(this.interval$);
      }
    }, 1000);
  }


  test() {
    const { privateKey, publicKey } = generateRsaKeyWithPKCS8();
    console.log(`生成的私钥为：\n${privateKey}`);
    console.log(`生成的公钥为：\n${publicKey}`);

    const cipherText = encryptByRSA(publicKey, 'password');
    console.log(`test加密后的内容为：\n${cipherText}`);

    const plainText = decryptByRSA(privateKey, cipherText as string);
    console.log(`解密后的内容为：\n${plainText}`);

    const signature = signBySHA256WithRSA(privateKey, 'password');
    console.log(`生成的签名：\n${signature}`);

    const isVerified = verifyBySHA256WithRSA(publicKey, signature, 'password');
    console.log(`是否验签通过：${isVerified}`);
  }

  submit(): void {
    this.error = '';
    if (this.type === 0) {
      this.userName.markAsDirty();
      this.userName.updateValueAndValidity();
      this.password.markAsDirty();
      this.password.updateValueAndValidity();
      if (this.userName.invalid || this.password.invalid) {
        return;
      }
    } else {
      this.mobile.markAsDirty();
      this.mobile.updateValueAndValidity();
      this.captcha.markAsDirty();
      this.captcha.updateValueAndValidity();
      if (this.mobile.invalid || this.captcha.invalid) {
        return;
      }
    }
    // 默认配置中对所有HTTP请求都会强制 [校验](https://ng-alain.com/auth/getting-started) 用户 Token
    // 然一般来说登录请求不需要校验，因此可以在请求URL加上：`/login?_allow_anonymous=true` 表示不触发用户 Token 校验
    this.loading = true;
    this.cdr.detectChanges();

    let encryptPassword = this.password.value;
    let encryptUsername = this.userName.value;

    let data = new FormData();
    data.append('name', encryptUsername as string);
    data.append('password', encryptPassword as string);
    this.http
      .post(
        Api.BaseAuthApi,
        data,
        {
        },
        {
          headers: {
            Authorization: 'Bearer dGVzdDp0ZXN0'
          },
          context: new HttpContext().set(ALLOW_ANONYMOUS, true)
        }
      )
      .pipe(
        finalize(() => {
          this.loading = false;
          this.cdr.detectChanges();
        })
      )
      .subscribe((res: any) => {
        if (res.code != ResponseCode.SUCCESS) {
          this.msg.error(res.data);
          return
        }
        this.msg.success("登录成功！");
        // 清空路由复用信息
        this.reuseTabService.clear();
        // 设置用户Token信息
        const token: ITokenModel = this.tokenService.get() || { token: null };
        token.token = "123456";
        this.tokenService.set(token);
        const user = { ...res.data, token: "123456" };
        const user1: any = {
          id:res.data.id,
          account_id:res.data.account_id,
          name: res.data.user_name,
          avatar: res.data.avatar,
          email: res.data.phone,
          phone: res.data.phone,
          username: res.data.account,
        };
        localStorage.setItem("user_id",res.data.id);
        localStorage.setItem("user_name",res.data.user_name);
        localStorage.setItem("sys_role_id",res.data.sys_role_id+"");
        this.settingService.setUser(user1);
        this.tokenService.set(user);
        // 重新获取 StartupService 内容，我们始终认为应用信息一般都会受当前用户授权范围而影响
        this.router.navigateByUrl('/');
      });
  }

  // #endregion

  ngOnDestroy(): void {
    if (this.interval$) {
      clearInterval(this.interval$);
    }
  }
}
